package com.yb.forum.utils;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.Version;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.AnnotationIntrospector;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.introspect.AnnotatedMember;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.List;
import java.util.concurrent.TimeUnit;

@Component
public class RedisCacheUtil {

    @Resource
    private StringRedisTemplate stringRedisTemplate;

    // ✅ 创建一个专用的 ObjectMapper：忽略 @JsonIgnore，包含所有字段（包括 null）
    private final ObjectMapper cacheObjectMapper = new ObjectMapper();

    public RedisCacheUtil() {
        // 包含 null 字段
        cacheObjectMapper.setSerializationInclusion(JsonInclude.Include.ALWAYS);

        // ✅ 关键：自定义 AnnotationIntrospector，忽略 @JsonIgnore
        cacheObjectMapper.setAnnotationIntrospector(new AnnotationIntrospector() {
            @Override
            public boolean hasIgnoreMarker(AnnotatedMember m) {
                return false; // 所有字段都不忽略
            }

            @Override
            public Version version() {
                return Version.unknownVersion();
            }
        });
    }

    // ===== 缓存普通对象 =====
    public <T> void setCacheObject(String key, T value, long timeout, TimeUnit timeUnit) {
        try {
            String json = cacheObjectMapper.writeValueAsString(value);
            stringRedisTemplate.opsForValue().set(key, json, timeout, timeUnit);
        } catch (JsonProcessingException e) {
            throw new RuntimeException("Redis 缓存序列化失败: " + key, e);
        }
    }

    public <T> T getCacheObject(String key, Class<T> clazz) {
        String json = stringRedisTemplate.opsForValue().get(key);
        if (json == null) return null;
        try {
            return cacheObjectMapper.readValue(json, clazz);
        } catch (JsonProcessingException e) {
            throw new RuntimeException("Redis 缓存反序列化失败: " + key, e);
        }
    }

    // ===== 缓存列表 =====
    public <T> void setCacheList(String key, List<T> list, long timeout, TimeUnit timeUnit) {
        try {
            String json = cacheObjectMapper.writeValueAsString(list);
            stringRedisTemplate.opsForValue().set(key, json, timeout, timeUnit);
        } catch (JsonProcessingException e) {
            throw new RuntimeException("Redis 列表序列化失败: " + key, e);
        }
    }

    public <T> List<T> getCacheList(String key, Class<T> elementType) {
        String json = stringRedisTemplate.opsForValue().get(key);
        if (json == null) return null;
        try {
            return cacheObjectMapper.readValue(json, new TypeReference<List<T>>() {});
        } catch (JsonProcessingException e) {
            throw new RuntimeException("Redis 列表反序列化失败: " + key, e);
        }
    }

    // ===== 删除缓存 =====
    public void delete(String key) {
        stringRedisTemplate.delete(key);
    }
}